import json
from typing import List, Any, Dict
from datetime import datetime
import asyncio
import threading

class ApiInterface:
    def __init__(self, db_manager, opcua_monitor):
        self.db_manager = db_manager
        self.opcua_monitor = opcua_monitor
        # 存储点位状态的字典
        self.point_statuses: Dict[int, Dict[str, Any]] = {}
        # 监控线程引用
        self.monitor_thread = None
        # 事件循环
        self.monitor_loop = None
        # 扫描间隔（秒）
        self.scan_interval = 10
        
        # 设置OPC UA监控状态更新回调
        self.opcua_monitor.set_status_callback(self._on_connection_status_update)
    
    def __call__(self):
        # 这个方法使对象可调用，但实际不需要做任何事情
        pass
    
    def _on_connection_status_update(self, point_id: int, status: str):
        """当OPC UA连接状态更新时调用"""
        # 更新点位状态
        self.point_statuses[point_id] = {
            'status': status,
            'last_check': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def get_all_points(self) -> List[Any]:
        """获取所有点位"""
        points = self.db_manager.get_all_points()
        # 为每个点位添加状态信息
        enriched_points = []
        for point in points:
            point_id = point[0]
            status_info = self.point_statuses.get(point_id, {'status': 'unknown', 'last_check': 'N/A'})
            # 构造包含状态信息的点位数据
            enriched_point = list(point) + [status_info['status'], status_info['last_check']]
            enriched_points.append(enriched_point)
        return enriched_points
    
    def get_point_by_id(self, params) -> Any:
        """根据ID获取点位"""
        point_id = params['point_id']
        return self.db_manager.get_point_by_id(point_id)
    
    def add_point(self, params) -> bool:
        """添加新点位"""
        try:
            name = params['name']
            url = params['url']
            node_id = params['node_id']
            self.db_manager.add_point(name, url, node_id)
            return True
        except Exception as e:
            print(f"添加点位失败: {e}")
            return False
    
    def update_point(self, params) -> bool:
        """更新点位"""
        try:
            point_id = params['point_id']
            name = params['name']
            url = params['url']
            node_id = params['node_id']
            return self.db_manager.update_point(point_id, name, url, node_id)
        except Exception as e:
            print(f"更新点位失败: {e}")
            return False
    
    def delete_point(self, params) -> bool:
        """删除点位"""
        try:
            point_id = params['point_id']
            # 同时删除状态信息
            if point_id in self.point_statuses:
                del self.point_statuses[point_id]
            return self.db_manager.delete_point(point_id)
        except Exception as e:
            print(f"删除点位失败: {e}")
            return False
    
    def toggle_point_status(self, params) -> bool:
        """切换点位启用/禁用状态"""
        try:
            point_id = params['point_id']
            return self.db_manager.toggle_point_status(point_id)
        except Exception as e:
            print(f"切换点位状态失败: {e}")
            return False
    
    def update_scan_interval(self, params) -> bool:
        """更新扫描间隔"""
        try:
            interval = int(params['interval'])
            if interval < 1 or interval > 3600:
                raise ValueError("扫描间隔必须在1-3600秒之间")
            
            self.scan_interval = interval
            # 更新OPC UA监控器的扫描间隔
            self.opcua_monitor.set_scan_interval(interval)
            return True
        except Exception as e:
            print(f"更新扫描间隔失败: {e}")
            return False
    
    def _run_monitor_loop(self):
        """在单独的线程中运行监控循环"""
        # 为监控线程创建新的事件循环
        self.monitor_loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.monitor_loop)
        self.monitor_loop.run_until_complete(self.opcua_monitor.monitor_all_points())
    
    def start_monitoring(self) -> bool:
        """开始监控"""
        try:
            # 如果已有监控线程在运行，先停止它
            if self.monitor_thread and self.monitor_thread.is_alive():
                self.opcua_monitor.stop_monitoring()
                # 等待线程结束
                self.monitor_thread.join(timeout=2)
            
            # 启动新的监控线程
            self.opcua_monitor.start_monitoring()
            self.monitor_thread = threading.Thread(target=self._run_monitor_loop, daemon=True)
            self.monitor_thread.start()
            return True
        except Exception as e:
            print(f"启动监控失败: {e}")
            return False
    
    def stop_monitoring(self) -> bool:
        """停止监控"""
        try:
            self.opcua_monitor.stop_monitoring()
            return True
        except Exception as e:
            print(f"停止监控失败: {e}")
            return False